package com.zygk.library.util;

/**
 * Created by Wikison on 2018/4/10.
 */
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.annotation.ColorInt;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.Layout.Alignment;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.AlignmentSpan;
import android.text.style.BackgroundColorSpan;
import android.text.style.BulletSpan;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.ImageSpan;
import android.text.style.LeadingMarginSpan;
import android.text.style.MaskFilterSpan;
import android.text.style.QuoteSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.ScaleXSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.SubscriptSpan;
import android.text.style.SuperscriptSpan;
import android.text.style.TypefaceSpan;
import android.text.style.URLSpan;
import android.text.style.UnderlineSpan;
import android.widget.TextView;

import static android.graphics.BlurMaskFilter.Blur;

/**
 * @author vondear
 * @date 2016/12/23
 */

public class RxTextTool {

  /**
   * 获取建造者
   *
   * @param text 样式字符串文本
   * @return {@link Builder}
   */
  public static Builder getBuilder(@NonNull CharSequence text, Context context) {
    return new Builder(text, context);
  }

  public static class Builder {
    private Context context;
    private int defaultValue = 0x12000000;
    private CharSequence text;

    private int flag;
    @ColorInt
    private int foregroundColor;
    @ColorInt
    private int backgroundColor;
    @ColorInt
    private int quoteColor;

    private boolean isLeadingMargin;
    private int first;
    private int rest;

    private boolean isBullet;
    private int gapWidth;
    private int bulletColor;

    private float proportion;
    private float xProportion;
    private boolean isStrikeThrough;
    private boolean isUnderline;
    private boolean isSuperscript;
    private boolean isSubscript;
    private boolean isBold;
    private boolean isItalic;
    private boolean isBoldItalic;
    private String fontFamily;
    private Alignment align;

    private boolean imageIsBitmap;
    private Bitmap bitmap;
    private boolean imageIsDrawable;
    private Drawable drawable;
    private boolean imageIsUri;
    private Uri uri;
    private boolean imageIsResourceId;
    @DrawableRes
    private int resourceId;

    private ClickableSpan clickSpan;
    private String url;

    private boolean isBlur;
    private float radius;
    private Blur style;

    private SpannableStringBuilder mBuilder;


    private Builder(@NonNull CharSequence text, Context context) {
      this.context= context;
      this.text = text;
      flag = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
      foregroundColor = defaultValue;
      backgroundColor = defaultValue;
      quoteColor = defaultValue;
      proportion = -1;
      xProportion = -1;
      mBuilder = new SpannableStringBuilder();
    }

    /**
     * 设置标识
     *
     * @param flag <ul>
     *             <li>{@link Spanned#SPAN_INCLUSIVE_EXCLUSIVE}</li>
     *             <li>{@link Spanned#SPAN_INCLUSIVE_INCLUSIVE}</li>
     *             <li>{@link Spanned#SPAN_EXCLUSIVE_EXCLUSIVE}</li>
     *             <li>{@link Spanned#SPAN_EXCLUSIVE_INCLUSIVE}</li>
     *             </ul>
     * @return {@link Builder}
     */
    public Builder setFlag(int flag) {
      this.flag = flag;
      return this;
    }

    /**
     * 设置前景色
     *
     * @param color 前景色
     * @return {@link Builder}
     */
    public Builder setForegroundColor(@ColorInt int color) {
      this.foregroundColor = color;
      return this;
    }

    /**
     * 设置背景色
     *
     * @param color 背景色
     * @return {@link Builder}
     */
    public Builder setBackgroundColor(@ColorInt int color) {
      this.backgroundColor = color;
      return this;
    }

    /**
     * 设置引用线的颜色
     *
     * @param color 引用线的颜色
     * @return {@link Builder}
     */
    public Builder setQuoteColor(@ColorInt int color) {
      this.quoteColor = color;
      return this;
    }

    /**
     * 设置缩进
     *
     * @param first 首行缩进
     * @param rest  剩余行缩进
     * @return {@link Builder}
     */
    public Builder setLeadingMargin(int first, int rest) {
      this.first = first;
      this.rest = rest;
      isLeadingMargin = true;
      return this;
    }

    /**
     * 设置列表标记
     *
     * @param gapWidth 列表标记和文字间距离
     * @param color    列表标记的颜色
     * @return {@link Builder}
     */
    public Builder setBullet(int gapWidth, int color) {
      this.gapWidth = gapWidth;
      bulletColor = color;
      isBullet = true;
      return this;
    }

    /**
     * 设置字体比例
     *
     * @param proportion 比例
     * @return {@link Builder}
     */
    public Builder setProportion(float proportion) {
      this.proportion = proportion;
      return this;
    }

    /**
     * 设置字体横向比例
     *
     * @param proportion 比例
     * @return {@link Builder}
     */
    public Builder setXProportion(float proportion) {
      this.xProportion = proportion;
      return this;
    }

    /**
     * 设置删除线
     *
     * @return {@link Builder}
     */
    public Builder setStrikeThrough() {
      this.isStrikeThrough = true;
      return this;
    }

    /**
     * 设置下划线
     *
     * @return {@link Builder}
     */
    public Builder setUnderline() {
      this.isUnderline = true;
      return this;
    }

    /**
     * 设置上标
     *
     * @return {@link Builder}
     */
    public Builder setSuperscript() {
      this.isSuperscript = true;
      return this;
    }

    /**
     * 设置下标
     *
     * @return {@link Builder}
     */
    public Builder setSubscript() {
      this.isSubscript = true;
      return this;
    }

    /**
     * 设置粗体
     *
     * @return {@link Builder}
     */
    public Builder setBold() {
      isBold = true;
      return this;
    }

    /**
     * 设置斜体
     *
     * @return {@link Builder}
     */
    public Builder setItalic() {
      isItalic = true;
      return this;
    }

    /**
     * 设置粗斜体
     *
     * @return {@link Builder}
     */
    public Builder setBoldItalic() {
      isBoldItalic = true;
      return this;
    }

    /**
     * 设置字体
     *
     * @param fontFamily 字体
     *                   <ul>
     *                   <li>monospace</li>
     *                   <li>serif</li>
     *                   <li>sans-serif</li>
     *                   </ul>
     * @return {@link Builder}
     */
    public Builder setFontFamily(@Nullable String fontFamily) {
      this.fontFamily = fontFamily;
      return this;
    }

    /**
     * 设置对齐
     *
     * @param align 对其方式
     *              <ul>
     *              <li>{@link Alignment#ALIGN_NORMAL}正常</li>
     *              <li>{@link Alignment#ALIGN_OPPOSITE}相反</li>
     *              <li>{@link Alignment#ALIGN_CENTER}居中</li>
     *              </ul>
     * @return {@link Builder}
     */
    public Builder setAlign(@Nullable Alignment align) {
      this.align = align;
      return this;
    }

    /**
     * 设置图片
     *
     * @param bitmap 图片位图
     * @return {@link Builder}
     */
    public Builder setBitmap(@NonNull Bitmap bitmap) {
      this.bitmap = bitmap;
      imageIsBitmap = true;
      return this;
    }

    /**
     * 设置图片
     *
     * @param drawable 图片资源
     * @return {@link Builder}
     */
    public Builder setDrawable(@NonNull Drawable drawable) {
      this.drawable = drawable;
      imageIsDrawable = true;
      return this;
    }

    /**
     * 设置图片
     *
     * @param uri 图片uri
     * @return {@link Builder}
     */
    public Builder setUri(@NonNull Uri uri) {
      this.uri = uri;
      imageIsUri = true;
      return this;
    }

    /**
     * 设置图片
     *
     * @param resourceId 图片资源id
     * @return {@link Builder}
     */
    public Builder setResourceId(@DrawableRes int resourceId) {
      this.resourceId = resourceId;
      imageIsResourceId = true;
      return this;
    }

    /**
     * 设置点击事件
     * <p>需添加view.setMovementMethod(LinkMovementMethod.getInstance())</p>
     *
     * @param clickSpan 点击事件
     * @return {@link Builder}
     */
    public Builder setClickSpan(@NonNull ClickableSpan clickSpan) {
      this.clickSpan = clickSpan;
      return this;
    }

    /**
     * 设置超链接
     * <p>需添加view.setMovementMethod(LinkMovementMethod.getInstance())</p>
     *
     * @param url 超链接
     * @return {@link Builder}
     */
    public Builder setUrl(@NonNull String url) {
      this.url = url;
      return this;
    }

    /**
     * 设置模糊
     * <p>尚存bug，其他地方存在相同的字体的话，相同字体出现在之前的话那么就不会模糊，出现在之后的话那会一起模糊</p>
     * <p>推荐还是把所有字体都模糊这样使用</p>
     *
     * @param radius 模糊半径（需大于0）
     * @param style  模糊样式<ul>
     *               <li>{@link Blur#NORMAL}</li>
     *               <li>{@link Blur#SOLID}</li>
     *               <li>{@link Blur#OUTER}</li>
     *               <li>{@link Blur#INNER}</li>
     *               </ul>
     * @return {@link Builder}
     */
    public Builder setBlur(float radius, Blur style) {
      this.radius = radius;
      this.style = style;
      this.isBlur = true;
      return this;
    }

    /**
     * 追加样式字符串
     *
     * @param text 样式字符串文本
     * @return {@link Builder}
     */
    public Builder append(@NonNull CharSequence text) {
      setSpan(context);
      this.text = text;
      return this;
    }

    /**
     * 创建样式字符串
     *
     * @return 样式字符串
     */
    public SpannableStringBuilder create() {
      setSpan(context);
      return mBuilder;
    }

    public void into(TextView textView) {
      setSpan(context);
      if (textView != null) {
        textView.setText(mBuilder);
      }
    }

    /**
     * 设置样式
     */
    private void setSpan(Context context) {
      int start = mBuilder.length();
      mBuilder.append(this.text);
      int end = mBuilder.length();
      if (foregroundColor != defaultValue) {
        mBuilder.setSpan(new ForegroundColorSpan(foregroundColor), start, end, flag);
        foregroundColor = defaultValue;
      }
      if (backgroundColor != defaultValue) {
        mBuilder.setSpan(new BackgroundColorSpan(backgroundColor), start, end, flag);
        backgroundColor = defaultValue;
      }
      if (isLeadingMargin) {
        mBuilder.setSpan(new LeadingMarginSpan.Standard(first, rest), start, end, flag);
        isLeadingMargin = false;
      }
      if (quoteColor != defaultValue) {
        mBuilder.setSpan(new QuoteSpan(quoteColor), start, end, 0);
        quoteColor = defaultValue;
      }
      if (isBullet) {
        mBuilder.setSpan(new BulletSpan(gapWidth, bulletColor), start, end, 0);
        isBullet = false;
      }
      if (proportion != -1) {
        mBuilder.setSpan(new RelativeSizeSpan(proportion), start, end, flag);
        proportion = -1;
      }
      if (xProportion != -1) {
        mBuilder.setSpan(new ScaleXSpan(xProportion), start, end, flag);
        xProportion = -1;
      }
      if (isStrikeThrough) {
        mBuilder.setSpan(new StrikethroughSpan(), start, end, flag);
        isStrikeThrough = false;
      }
      if (isUnderline) {
        mBuilder.setSpan(new UnderlineSpan(), start, end, flag);
        isUnderline = false;
      }
      if (isSuperscript) {
        mBuilder.setSpan(new SuperscriptSpan(), start, end, flag);
        isSuperscript = false;
      }
      if (isSubscript) {
        mBuilder.setSpan(new SubscriptSpan(), start, end, flag);
        isSubscript = false;
      }
      if (isBold) {
        mBuilder.setSpan(new StyleSpan(Typeface.BOLD), start, end, flag);
        isBold = false;
      }
      if (isItalic) {
        mBuilder.setSpan(new StyleSpan(Typeface.ITALIC), start, end, flag);
        isItalic = false;
      }
      if (isBoldItalic) {
        mBuilder.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), start, end, flag);
        isBoldItalic = false;
      }
      if (fontFamily != null) {
        mBuilder.setSpan(new TypefaceSpan(fontFamily), start, end, flag);
        fontFamily = null;
      }
      if (align != null) {
        mBuilder.setSpan(new AlignmentSpan.Standard(align), start, end, flag);
        align = null;
      }
      if (imageIsBitmap || imageIsDrawable || imageIsUri || imageIsResourceId) {
        if (imageIsBitmap) {
          mBuilder.setSpan(new ImageSpan(context, bitmap), start, end, flag);
          bitmap = null;
          imageIsBitmap = false;
        } else if (imageIsDrawable) {
          mBuilder.setSpan(new ImageSpan(drawable), start, end, flag);
          drawable = null;
          imageIsDrawable = false;
        } else if (imageIsUri) {
          mBuilder.setSpan(new ImageSpan(context, uri), start, end, flag);
          uri = null;
          imageIsUri = false;
        } else {
          mBuilder.setSpan(new ImageSpan(context, resourceId), start, end, flag);
          resourceId = 0;
          imageIsResourceId = false;
        }
      }
      if (clickSpan != null) {
        mBuilder.setSpan(clickSpan, start, end, flag);
        clickSpan = null;
      }
      if (url != null) {
        mBuilder.setSpan(new URLSpan(url), start, end, flag);
        url = null;
      }
      if (isBlur) {
        mBuilder.setSpan(new MaskFilterSpan(new BlurMaskFilter(radius, style)), start, end, flag);
        isBlur = false;
      }
      flag = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
    }
  }

          //RxTextTool.getBuilder("").setBold().setAlign(Layout.Alignment.ALIGN_CENTER)
          //      .append("测试").append("Url\n").setUrl(URL_VONTOOLS)
          //      .append("列表项\n").setBullet(60, getResources().getColor(R.color.blue_baby))
          //      .append("  测试引用\n").setQuoteColor(getResources().getColor(R.color.blue_baby))
          //      .append("首行缩进\n").setLeadingMargin(30, 50)
          //      .append("测试").append("上标").setSuperscript().append("下标\n").setSubscript()
          //      .append("测试").append("点击事件\n").setClickSpan(clickableSpan)
          //      .append("测试").append("serif 字体\n").setFontFamily("serif")
          //      .append("测试").append("图片\n").setResourceId(R.drawable.logo)
          //      .append("测试").append("前景色").setForegroundColor(Color.GREEN).append("背景色\n").setBackgroundColor(getResources().getColor(R.color.blue_baby))
          //      .append("测试").append("删除线").setStrikethrough().append("下划线\n").setUnderline()
          //      .append("测试").append("sans-serif 字体\n").setFontFamily("sans-serif")
          //      .append("测试").append("2倍字体\n").setProportion(2)
          //      .append("测试").append("monospace字体\n").setFontFamily("monospace")
          //      .append("测试").append("普通模糊效果字体\n").setBlur(3, BlurMaskFilter.Blur.NORMAL)
          //      .append("测试").append(" 粗体 ").setBold().append(" 斜体 ").setItalic().append(" 粗斜体 \n").setBoldItalic()
          //      .append("测试").append("横向2倍字体\n").setXProportion(2)
          //      .append("\n测试正常对齐\n").setAlign(Layout.Alignment.ALIGN_NORMAL)
          //      .append("测试居中对齐\n").setAlign(Layout.Alignment.ALIGN_CENTER)
          //      .append("测试相反对齐\n").setAlign(Layout.Alignment.ALIGN_OPPOSITE)
          //      .into(mTvAboutSpannable);
}
